package com.wenhai.spring.bean.scope;

import com.wenhai.xiaomage.spring.ioc.overview.dependency.domain.User;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;

import java.util.Map;

/**
 * @Author:wenhai
 * @Description: Spring Bean Scope
 * @Date:2020/3/15
 */
//@EnableWebMvc
public class BeanScopeDemo implements DisposableBean {

    @Autowired
    private DefaultListableBeanFactory beanFactory;



    @Autowired
    @Qualifier("singletonUser")
    private User singletonUser;

    @Autowired
    @Qualifier("singletonUser")
    private User singletonUser1;

    @Autowired
    @Qualifier("prototypeUser")
    private User prototypeUser;

    @Autowired
    @Qualifier("prototypeUser")
    private User prototypeUser1;

    @Autowired
    @Qualifier("prototypeUser")
    private User prototypeUser2;

//    @Autowired
//    private User servletContextUser;

    @Autowired
    private Map<String,User> users;

    @Bean
    public static User singletonUser() {
        return createUser();
    }

    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public static User prototypeUser() {
        return createUser();
    }

//    @Bean
//    @ApplicationScope
//    public static User servletContextUser() {
//        return createUser();
//    }

    private static User createUser() {
        User user = new User();
        user.setId(System.nanoTime());
        return user;
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext cxt = new AnnotationConfigApplicationContext();
        cxt.register(BeanScopeDemo.class);
        cxt.refresh();
//        scopedBeansForLookup(cxt);
        scopedBeansForInjection(cxt);
        cxt.close();
    }

    private static void scopedBeansForInjection(AnnotationConfigApplicationContext cxt) {
        BeanScopeDemo bean = cxt.getBean(BeanScopeDemo.class);
        System.out.println("bean.singletonUser = " + bean.singletonUser);
        System.out.println("bean.singletonUser1 = " + bean.singletonUser1);
        System.out.println("bean.prototypeUser = " + bean.prototypeUser);
        System.out.println("bean.prototypeUser2 = " + bean.prototypeUser2);
        System.out.println("bean.prototypeUser1 = " + bean.prototypeUser1);
        System.out.println("bean.users = " + bean.users);
//        System.out.println("bean.servletContextUser = " + bean.servletContextUser);
    }

    private static void scopedBeansForLookup(AnnotationConfigApplicationContext cxt) {
        for (int i = 0; i < 3; i++) {
            User singletonUser = cxt.getBean("singletonUser", User.class);
            System.out.println(singletonUser);
            System.out.println("---------------------");
            User prototypeUser = cxt.getBean("prototypeUser", User.class);
            System.out.println(prototypeUser);
        }
    }

    @Override
    public void destroy() throws Exception {

        System.out.println("当前 BeanScopeDemo Bean 正在销毁中。。。。。。。。");
        this.prototypeUser.destroy();
        this.prototypeUser1.destroy();
        this.prototypeUser2.destroy();

        for (Map.Entry<String, User> userEntry : this.users.entrySet()) {
            if (beanFactory.getBeanDefinition(userEntry.getKey()).isPrototype()) {
                userEntry.getValue().destroy();
            }
        }
    }
}
